# Copyright (c) 2019 Presto Labs Pte. Ltd.
# Author: jaewon

import wrapt

from coin.base.book.price_map import AskPriceMap, BidPriceMap


class PriceMapObserverBase:
  def on_clear(self):
    pass

  def on_update(self, price, entry):
    pass


class ObservablePriceMap(wrapt.ObjectProxy):
  def __init__(self, observer, subject_price_map):
    super().__init__(subject_price_map)
    self._observer = observer

  def __del__(self):
    self._observer = None

  def clear(self):
    self.__wrapped__.clear()
    self._observer.on_clear()

  def __setitem__(self, price: float, entry):
    self.__wrapped__.__setitem__(price, entry)
    self._observer.on_update(price, entry)

  def __delitem__(self, price: float):
    self.__wrapped__.__delitem__(price)
    self._observer.on_update(price, None)

  def notify_updated(self, price, entry):
    self.__wrapped__.notify_updated(price, entry)
    self._observer.on_update(price, entry)

  def send_snapshot_to_observer(self):
    self._observer.on_clear()
    for price, entry in self.__wrapped__.iteritems():
      self._observer.on_update(price, entry)

  @property
  def underlying_price_map(self):
    return self.__wrapped__


class ObservableAskPriceMap(ObservablePriceMap):
  def __init__(self, observer, subject_ask_price_map=None):
    if subject_ask_price_map is None:
      subject_ask_price_map = AskPriceMap()
    super().__init__(observer, subject_ask_price_map)


class ObservableBidPriceMap(ObservablePriceMap):
  def __init__(self, observer, subject_bid_price_map=None):
    if subject_bid_price_map is None:
      subject_bid_price_map = BidPriceMap()
    super().__init__(observer, subject_bid_price_map)
